/**
 * @author David Young
 */
package csab.core;

import java.awt.Rectangle;

import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;

/**
 * The TerrainCollidable object is an object which is meant
 * to serve as a blocking/terrain mechanism for the game engine.
 * @author David Young
 */
public class TerrainCollidable extends Collidable {
	public static boolean debugTerrain = false;
	public static boolean getDebugState()
	{
		return debugTerrain;
	}
	
	public static void setDebugState(boolean state)
	{
		debugTerrain = state;
	}
	
	//Are we a background platform (side collisions okay?)
	private boolean bgplatform;
	
	/**
	 * Takes 4 parameters and constructs a TerrainCollidable object
	 * at the specified x and y coordinates with the appropriate
	 * width (w) and height (h).
	 * @param x The x-axis location of this object.
	 * @param y The y-axis location of this object.
	 * @param w The width of this object.
	 * @param h The height of this object.
	 * @param isPlatform Specifies whether or not this TerrainCollidable is a platform.
	 */
	public TerrainCollidable(int x, int y, int w, int h, boolean isPlatform)
	{
		super("terrain");
		boundingbox = new Rectangle(x, y, w, h);
		setPos(x,y);
		setWidth(w);
		setHeight(h);
		bgplatform = isPlatform;
	}
	
	/**
	 * Checks to see if item collides with this object.
	 * This does not collide with objects of type View.
	 * @see csab.core.View
	 * @see csab.core.Collidable
	 */
	public boolean collides(Collidable item) {
		if(item instanceof View && 
		   !TerrainCollidable.debugTerrain)
			return false;
		else
			return super.collides(item);
	}
	
	/* (non-Javadoc)
	 * @see csab.core.Entity#destroy()
	 */
	@Override
	public void destroy() {}
	
	/**
	 * This is a callback method which is designed to check if the Collidable
	 * parameter matches the bounding rules of this TerrainCollidable. If not,
	 * the object is displaced to a position on the perimeter of this TerrainCollidable.
	 * @param obj Collidable to perform collision against.
	 * @see csab.core.Collidable
	 */
	public void doCollide(Collidable obj) {
		//Ignore other terrain. Shouldn't have to check this.
		if(!obj.canCollide() || obj instanceof TerrainCollidable || obj instanceof View)
			return;
		
		Rectangle cbox = obj.getCollisionBox();
		
		//We landed on the platform
		if(bgplatform)
		{
			//Calculate last collision box location
			int cLeft = (int)cbox.x;
			int cRight = (int)cbox.x + cbox.width;
			int cbot = (int)cbox.y + cbox.height;
			
			int left = boundingbox.x;
			int right = boundingbox.x + boundingbox.width;
			int top = boundingbox.y;

			int bot = boundingbox.y + boundingbox.height;
			
			if(cbot >= top && cRight > left && cLeft < right && obj.getVY() > 0 &&
			   !(cbot > bot - (bot - top) / 2))
			{

				if(obj instanceof Sprite)
				{
					Sprite temp = (Sprite)obj;
					temp.landed();
					if(temp.getVY() >= temp.getDmgFallVel())
					{
						temp.doDamage(temp.getFallDamage());
					}
				}
				obj.setBased(true);
				obj.setY(top-cbox.height+1);
				obj.setLastY(obj.getY());
				obj.setVY(0);
			}
		}
		else //We crashed into a terrain piece
		{	
			//Calculate last collision box location
			int lcLeft = (cbox.x - (int)obj.getX()) + (int)obj.getLastX();
			int lcTop = (cbox.y - (int)obj.getX()) + (int)obj.getLastY();
			int lcRight = lcLeft + cbox.width; 
			int lcBot = lcTop + cbox.height;
			
			int cLeft = (int)cbox.x;
			int cRight = (int)cbox.x + cbox.width;
			int ctop = (int)cbox.y;
			int cbot = (int)cbox.y + cbox.height;
			
			int left = boundingbox.x;
			int right = boundingbox.x + boundingbox.width;
			int top = boundingbox.y;
			int bot = boundingbox.y + boundingbox.height;
			
			//Collision on the left side
			if(lcRight <= left && cRight > left && 
			   ((lcTop > top || lcBot < bot) ||
			    (lcTop <= top && lcBot >= bot)))
			{
				obj.setX(left-cbox.width);
				obj.setLastX(obj.getX());
				obj.setVX(0);
			}//Collision on the right side
			else if(lcLeft >= right && cLeft < right && 
			    ((lcTop >= top || lcBot <= bot) ||
			     (lcTop <= top && lcBot >= bot)))
			{
				obj.setX(right);
				obj.setLastX(obj.getX());
				obj.setVX(0);
			}//Collision from bot
			else if(ctop <= bot && obj.getVY() <= 0)
			{
				obj.setY(bot+1);
				obj.setLastY(obj.getY());
				obj.setVY(0);
			}//Collision from top
			else if(cbot >= top)
			{
				obj.setBased(true);
				if(obj instanceof Sprite)
				{
					Sprite temp = (Sprite)obj;
					temp.landed();
					if(temp.getVY() >= temp.getDmgFallVel())
					{
						temp.doDamage(temp.getFallDamage());
					}
				}
				obj.setY(top-cbox.height+1);
				obj.setLastY(obj.getY());
				obj.setVY(0);
			}//wat
			else
			{
				obj.setVel(0, 0);
				obj.setY(top-cbox.height);
				obj.setLastY(obj.getY());
			}
		}
		
	}

	/**
	 * Draws a rectangle for debugging if it is set to do so.
	 * @see csab.core.Entity
	 */
	public void draw(int x, int y, Graphics g)
	{
		if(debugTerrain) {
			g.setColor(Color.yellow);
			g.drawRect(x, y, boundingbox.width, boundingbox.height);
		}
	}

}
